// Cow Marathon, POJ 1985
// 陈锋
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <vector>

const int MAXN = 1e6 + 4;
struct Edge {
  Edge(int _v, int _w) : v(_v), w(_w) {}
  int v, w;
};
using namespace std;
int N, M, ans;
vector<Edge> G[MAXN];
int D[MAXN];

void dfs(int u, int fa) {
  int &d = D[u], d1 = 0;  // D到不同子树叶子的第1,2长路径
  d = 0;
  for (size_t i = 0; i < G[u].size(); i++) {
    const Edge& e = G[u][i];
    if (e.v == fa) continue;
    dfs(e.v, u);
    int nd = e.w + D[e.v];
    if (nd >= d)
      d1 = d, d = nd;
    else if (nd > d1)
      d1 = nd;
  }
  ans = max(ans, d + d1);
}

int main() {
  scanf("%d %d", &N, &M);
  char S[8];
  for (int i = 1, u, v, w; i <= M; i++) {
    scanf("%d %d %d %s", &u, &v, &w, S);
    G[u].push_back(Edge(v, w)), G[v].push_back(Edge(u, w));
  }
  ans = -1;
  dfs(1, -1);
  printf("%d\n", ans);
  return 0;
}
/*
算法分析请参考: 《入门经典-第2版》 9.4.2一节 树的最长路径
需要注意同一个节点往下的最长路以及第二长路的更新方法
*/
// Accepted 1219ms 16560kB 863 G++ 2020-12-08 21:00:06 22197159